home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / lfsrebuild / lfsrebuild.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-12  |  57.2 KB  |  2,001 lines

  1. /* 
  2.  * lfsrebuild.c --
  3.  *
  4.  *    The lfsrebuild program - Rebuild an LFS file system's metadata 
  5.  *    structures and restore the file system to a consistent state. This
  6.  *    program should be run after metadata corruption is detected in a 
  7.  *    LFS file system. 
  8.  *
  9.  * Copyright 1989 Regents of the University of California
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any purpose and without
  12.  * fee is hereby granted, provided that the above copyright
  13.  * notice appear in all copies.  The University of California
  14.  * makes no representations about the suitability of this
  15.  * software for any purpose.  It is provided "as is" without
  16.  * express or implied warranty.
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /user2/mendel/lfs/src/cmds/checkLfs/RCS/checkLfs.c,v 1.1 90/06/01 10:10:18 mendel Exp Locker: mendel $ SPRITE (Berkeley)";
  21. #endif /* not lint */
  22.  
  23. #ifdef __STDC__
  24. #define _HAS_PROTOTYPES
  25. #endif
  26.  
  27. #include <cfuncproto.h>
  28. #include <varargs.h>
  29. #include <sprite.h>
  30. #include <stdio.h>
  31. #include <sys/types.h>
  32. #include <option.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <sys/file.h>
  36. #include <alloca.h>
  37. #include <bstring.h>
  38. #include <unistd.h>
  39. #include <bit.h>
  40. #include <time.h>
  41. #include <sys/time.h>
  42. #include <fs.h>
  43. #include <kernel/fs.h>
  44. #include <kernel/dev.h>
  45. #include <kernel/fsdm.h>
  46. #include <kernel/fslcl.h>
  47. #include <kernel/devDiskLabel.h>
  48.  
  49. #include <kernel/lfsDesc.h>
  50. #include <kernel/lfsDescMap.h>
  51. #include <kernel/lfsFileLayout.h>
  52. #include <kernel/lfsDirOpLog.h>
  53. #include <kernel/lfsSegLayout.h>
  54. #include <kernel/lfsStableMem.h>
  55. #include <kernel/lfsSuperBlock.h>
  56. #include <kernel/lfsUsageArray.h>
  57. #include <kernel/lfsStats.h>
  58.  
  59. #include "fscheck.h"
  60. #include "layout.h"
  61.  
  62. /*
  63.  * The super block of the file system.
  64.  */
  65. LfsSuperBlock    *superBlockPtr;
  66. int        currentTimestamp;
  67. /*
  68.  * The descriptor map and segment usage array of file system.
  69.  */
  70. ClientData descMapDataPtr;        /* Descriptor map of file system. */
  71. LfsDescMapCheckPoint *descMapCheckPointPtr; /* Most current descriptor map 
  72.                          * check point. */
  73. LfsSegUsageCheckPoint    *usageCheckPointPtr;
  74. FdInfo        *descInfoArray;
  75.  
  76. ClientData   usageArrayDataPtr;    /* Data of usage map. */
  77.  
  78.  
  79. typedef struct Seg {
  80.     int      segNo;    /* Segment number. */
  81.     int      segSizeInBlocks;    /* Segment size in blocks. */
  82.     int   diskFd;        /* Open file of disk. */
  83. } Seg;
  84.  
  85. /*
  86.  * Info kept for each block in the file system while running in full check
  87.  * mode. We use bit fields to keep the size down.
  88.  */
  89.  
  90. typedef struct BlockInfo {
  91.     int     found:1;    /* TRUE if found in summary region. */
  92.     int        type :4;    /* Type of block. See defines below. */
  93.     int     tversion:7; /* Trunc version if file. */
  94.     int     blockNum:20; /* Block number of block's owner. */
  95.     int     fileNum;    /* File number of block's owner. */
  96.  
  97. } BlockInfo;
  98.  
  99. #define    SAME_VERSION(version, binfo) \
  100.         (((version) & 0x7f) == ((binfo).tversion)&0x7f)
  101. /*
  102.  * Block info types. 
  103.  *    UNUSED    - Not allocated.
  104.  *    FILE    - Owned by a file. FileNum and blockNum specify the file
  105.  *          and block.
  106.  *    DESC_MAP - A block of the descriptor map. BlockNum specifies the block.
  107.  *    USAGE_ARRAY - A block of the segment usage array.
  108.  *    SUMMARY        - Block is a summary block.
  109.  *    CHECKPOINT  - Block is a checkpoint block.
  110.  *    DESC        - Block contains file descriptors.
  111.  *    DIRLOG        - Directory log block
  112.  */
  113. #define    UNUSED    0
  114. #define    FILE    1
  115. #define    DESC_MAP 2
  116. #define USAGE_ARRAY 3
  117. #define    SUMMARY        4
  118. #define CHECKPOINT  5
  119. #define    DESC       6
  120. #define    DIRLOG        7
  121. #define    UNKNOWN   8
  122.  
  123. char    *blockTypeNames[UNKNOWN+1] = { 
  124.     "Unused", "File", "DescMap" , "UsageArray", "Summary", "Checkpoint",
  125.     "Descriptor", "DirLog", "Unknown" 
  126. };
  127.  
  128. BlockInfo    *blockInfoArray;  /* BlockInfo for each block in fs. */
  129. int        *usageBitMap;      /* Bit map of block usage during quick check
  130.                    * of file system. */
  131. int        *foundBitMap;      /* Bit map of block found during summary
  132.                    * check. */
  133. int        *descBlockBitMap;      /* Bit map of desc blocks. */
  134. int        numBlocks;      /* Number of blocks in fs. */
  135.  
  136. int    *activeBytesArray;    /* Computed active bytes for each segment. */
  137.  
  138. static Boolean computeUsageArray;
  139.  
  140. int    minorErrors;
  141. int    majorErrors;
  142.  
  143. /*
  144.  * Arguments.
  145.  */
  146. int    blockSize = 512;    /* File system block size. */
  147. int    superBlockOffset = 64;    /* Offset of super block. */
  148. Boolean dumpFlag = FALSE;    /* Dump version description of file system. */
  149. Boolean showDirLog = FALSE;    /* Show the directory log. */
  150. Boolean    verboseFlag = FALSE;    /* Trace progress of program. */
  151. char    *deviceName;        /* Device to use. */
  152. Boolean    full = FALSE;
  153. Boolean oldcp = FALSE;
  154. Boolean shownew = FALSE;
  155. Boolean doWrites = FALSE;
  156.  
  157. Option optionArray[] = {
  158.     {OPT_DOC, (char *) NULL,  (char *) NULL,
  159.     "Check a LFS file system and report problems.\n Synopsis: \"checkLfs [switches] deviceName\"\n Command-line switches are:"},
  160.     {OPT_INT, "blockSize", (Address) &blockSize, 
  161.     "Block size of file system."},
  162.     {OPT_INT, "superBlockOffset", (Address) &superBlockOffset, 
  163.     "Offset into device of the superBlock."},
  164.     {OPT_TRUE, "dump", (Address) &dumpFlag, 
  165.     "Print out a description of file system."},
  166.     {OPT_TRUE, "showDirLog", (Address) &showDirLog, 
  167.     "Print out the directory operation log."},
  168.     {OPT_TRUE, "full", (Address) &full, 
  169.     "Full a full error analysis."},
  170.     {OPT_TRUE, "verbose", (Address) &verboseFlag, 
  171.     "Output progress messages during execution."},
  172.     {OPT_TRUE, "oldcp", (Address) &oldcp, 
  173.     "Output progress messages during execution."},
  174.     {OPT_TRUE, "shownew", (Address) &shownew, 
  175.     "Print new metadata to standard out."},
  176.     {OPT_TRUE, "write", (Address) &doWrites, 
  177.     "Write new metadata to disk."},
  178. };
  179. /*
  180.  * Forward routine declartions.
  181.  */
  182. extern Boolean AllocUsageArray _ARGS_(());
  183. extern Boolean AllocDescMap _ARGS_(());
  184. extern char *GetUsageState _ARGS_((LfsSegUsageEntry *entryPtr));
  185. static void FindAllFiles _ARGS_((int diskFd));
  186. static Boolean CheckFile _ARGS_((int diskFd, int fileNum,             
  187.             LfsFileDescriptor *descPtr));
  188. static Boolean CheckIndirectBlock _ARGS_((int diskFd, int fileNum, 
  189.         LfsFileDescriptor *descPtr, int blockNum, int blockAddress));
  190. static Boolean CheckBlock _ARGS_((int diskFd, int fileNum, 
  191.         LfsFileDescriptor *descPtr, int blockNum, int blockAddress));
  192. static void ComputeUsageArray _ARGS_((int diskFd));
  193. static void BuildUsageArray _ARGS_((int diskFd));
  194. static void CheckSummaryRegions _ARGS_((int diskFd));
  195. static void CheckSegUsageSummary _ARGS_((int diskFd, Seg *segPtr, int timestamp,
  196.     int startAddress, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  197. static void CheckDescMapSummary _ARGS_((int diskFd, Seg *segPtr, int timestamp,
  198.     int startAddress, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  199. static void CheckFileLayoutSummary _ARGS_((int diskFd, Seg *segPtr,
  200.             int timestamp,
  201.     int startAddr, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  202. static char *GetOwner _ARGS_((int blockNum));
  203. static void PrintSuperBlock _ARGS_((LfsSuperBlock *superBlockPtr));
  204. static void PrintCheckPointHdr _ARGS_((LfsCheckPointHdr *headerPtr, int region));
  205. static ClientData AllocStableMem _ARGS_((LfsStableMemParams *smemParamsPtr,  int type));
  206. static void SetStableMemBlockIndex _ARGS_((ClientData clientData, int blockNum, int address));
  207. static void ShowDirLogBlock _ARGS_((LfsDirOpLogBlockHdr *hdrPtr, int addr));
  208.  
  209. static char *FmtTime _ARGS_((void));
  210. static Seg *SegInit _ARGS_((int diskFd, int segNumber));
  211. static int SegStartAddr _ARGS_((Seg *segPtr));
  212. static char *SegFetchBlock _ARGS_((Seg *segPtr, int blockOffset, int size));
  213. static void SegReleaseBlock _ARGS_((Seg *segPtr, char *memPtr));
  214. static void SegRelease _ARGS_((Seg *segPtr));
  215. static Boolean IsZero _ARGS_((char *dataPtr, int size));
  216.  
  217. extern int open();
  218. extern void panic();
  219. extern int gettimeofday _ARGS_((struct timeval *tp, struct timezone *tzp));
  220.  
  221. /*
  222.  *----------------------------------------------------------------------
  223.  *
  224.  * main --
  225.  *
  226.  *    Main routine of lfsrebuild - parse arguments and do the work.
  227.  *
  228.  * Results:
  229.  *    None.
  230.  *
  231.  * Side effects:
  232.  *    None.
  233.  *
  234.  *----------------------------------------------------------------------
  235.  */
  236.  
  237. int
  238. main(argc,argv)
  239.     int    argc;
  240.     char *argv[];
  241. {
  242.     int       diskFd, maxCheckPointSize;
  243.     LfsCheckPointHdr    checkPointHdr[2];
  244.     LfsCheckPointHdr    *checkPointHdrPtr = (LfsCheckPointHdr *) NULL;
  245.     char        *checkPointPtr, *trailerPtr = (char *) NULL;
  246.     LfsCheckPointTrailer *trailPtr = (LfsCheckPointTrailer *) NULL;
  247.     Boolean        gotOne;
  248.     int            choosenOne, i, try;
  249.     int            checkPointSize;
  250.  
  251.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray), 0);
  252.     if (argc != 2) { 
  253.          Opt_PrintUsage(argv[0], optionArray, Opt_Number(optionArray));
  254.      exit(EXIT_BAD_ARG);
  255.     } else {
  256.     deviceName = argv[1];
  257.     }
  258.     diskFd = open(deviceName, doWrites ? O_RDWR : O_RDONLY, 0);
  259.     if (diskFd < 0) {
  260.     fprintf(stderr,"%s:", argv[0]);
  261.     perror(deviceName);
  262.     exit(EXIT_HARD_ERROR);
  263.     }
  264.     /*
  265.      * Fill in the super block header.
  266.      */
  267.     superBlockPtr = (LfsSuperBlock *) malloc(LFS_SUPER_BLOCK_SIZE);
  268.     if (DiskRead(diskFd, superBlockOffset, sizeof(LfsSuperBlock), 
  269.         (char *)superBlockPtr) != sizeof(LfsSuperBlock)) {
  270.     fprintf(stderr,"%s:Can't read superblock.\n", deviceName);
  271.     exit(EXIT_READ_FAILURE);
  272.  
  273.     }
  274.     if (superBlockPtr->hdr.magic != LFS_SUPER_BLOCK_MAGIC) {
  275.     fprintf(stderr,"%s:Bad magic number for filesystem\n", deviceName);
  276.     exit(EXIT_READ_FAILURE);
  277.     }
  278.     if (dumpFlag) {
  279.        PrintSuperBlock(superBlockPtr);
  280.     }
  281.  
  282.     /*
  283.      * Examine the two checkpoint areas to locate the checkpoint area with the
  284.      * newest timestamp.
  285.      */
  286.     if (DiskRead(diskFd, superBlockPtr->hdr.checkPointOffset[0],
  287.         sizeof(LfsCheckPointHdr), (char *) (checkPointHdr+0)) != 
  288.     sizeof(LfsCheckPointHdr)) {
  289.     fprintf(stderr,"%s:Can't read checkPointHeader 0.\n", deviceName);
  290.     checkPointHdr[0].timestamp = 0;
  291.     }
  292.     if (dumpFlag) {
  293.     PrintCheckPointHdr(checkPointHdr, 0);
  294.     }
  295.     if (DiskRead(diskFd, superBlockPtr->hdr.checkPointOffset[1],
  296.         sizeof(LfsCheckPointHdr), (char *) (checkPointHdr+1))  != 
  297.     sizeof(LfsCheckPointHdr)) {
  298.     fprintf(stderr,"%s:Can't read checkPointHeader 1.\n", deviceName);
  299.     checkPointHdr[1].timestamp = 0;
  300.     }
  301.     if (dumpFlag) {
  302.     PrintCheckPointHdr(checkPointHdr+1, 1);
  303.     }
  304.  
  305.     maxCheckPointSize = superBlockPtr->hdr.maxCheckPointBlocks * 
  306.                 blockSize;
  307.     checkPointPtr = malloc(maxCheckPointSize);
  308.     choosenOne = (checkPointHdr[0].timestamp<checkPointHdr[1].timestamp) ?
  309.                 1 : 0;
  310.     currentTimestamp = checkPointHdr[choosenOne].timestamp+1;
  311.     numBlocks = superBlockPtr->usageArray.numberSegments * 
  312.             (superBlockPtr->usageArray.segmentSize/blockSize) +
  313.              superBlockPtr->hdr.logStartOffset;
  314.     /*
  315.      * Allocate the blockInfoArray for the file system. Zero 
  316.      * marks all blocks as UNUSED.
  317.      */
  318.     blockInfoArray = (BlockInfo *) calloc(numBlocks, sizeof(BlockInfo));
  319.     /*
  320.      * Mark blocks upto log start as checkpoint blocks.
  321.      */
  322.     for (i = 0; i < superBlockPtr->hdr.logStartOffset; i++) {
  323.         blockInfoArray[i].type = CHECKPOINT;
  324.         blockInfoArray[i].found = TRUE;
  325.     }
  326.     /*
  327.      * Allocate the descriptor found array. Zero marks all descriptors
  328.      * as unallocated.
  329.      */
  330.     descInfoArray = (FdInfo *) calloc(superBlockPtr->descMap.maxDesc, 
  331.                     sizeof(FdInfo));
  332.  
  333.     /*
  334.      * Allocate the real active bytes array. Initialize each entry to zero
  335.      * bytes used.
  336.      */
  337.     activeBytesArray = (int *) calloc(superBlockPtr->usageArray.numberSegments,
  338.                     sizeof(activeBytesArray[0]));
  339.     if (oldcp) {
  340.     choosenOne = !choosenOne;
  341.     }
  342.     gotOne = FALSE;
  343.     for (try = 0; (try <= 1) && !gotOne; try++) {
  344.     if (verboseFlag) {
  345.         printf("%s:Read LFS checkpoint %d from %s\n", FmtTime(), choosenOne,
  346.             deviceName);
  347.     }
  348.     if (DiskRead(diskFd, superBlockPtr->hdr.checkPointOffset[choosenOne],
  349.             maxCheckPointSize, checkPointPtr) != maxCheckPointSize) {
  350.         fprintf(stderr,"%s:Can't read checkPoint %d\n", deviceName, choosenOne);
  351.         continue;
  352.     }
  353.  
  354.  
  355.     checkPointHdrPtr = (LfsCheckPointHdr *) checkPointPtr;
  356.     trailerPtr = (checkPointPtr + checkPointHdrPtr->size - 
  357.                     sizeof(LfsCheckPointTrailer));
  358.     trailPtr = (LfsCheckPointTrailer *) trailerPtr;
  359.     if (trailPtr->timestamp != checkPointHdrPtr->timestamp) {
  360.         fprintf(stderr,"%s:Header timestamp %d doesn't match trailer timestamp %d on checkpoint %d\n", deviceName, checkPointHdrPtr->timestamp, 
  361.                 trailPtr->timestamp, choosenOne);
  362.         continue;
  363.     }
  364.     if (dumpFlag) {
  365.         printf("Using checkpoint area %d with timestamp %d domain %d (%s)\n",
  366.         choosenOne, checkPointHdrPtr->timestamp, 
  367.         checkPointHdrPtr->domainNumber, checkPointHdrPtr->domainPrefix);
  368.     }
  369.  
  370.     gotOne = TRUE;
  371.  
  372.     }
  373.     if (!gotOne) {
  374.     fprintf(stderr,"%s:Can't find good checkpoint region.\n");
  375.     }
  376.     AllocUsageArray();
  377.     AllocDescMap();
  378.     if (verboseFlag) {
  379.     printf("%s:Checking summary regions\n", FmtTime());
  380.     }
  381.     CheckSummaryRegions(diskFd);
  382.  
  383.     FindAllFiles(diskFd);
  384.     if (verboseFlag) {
  385.     printf("%s:Checking usage array\n",FmtTime());
  386.     }
  387.     ComputeUsageArray(diskFd);
  388.     BuildUsageArray(diskFd);
  389.     if (verboseFlag) {
  390.     printf("%s:Checking directory tree\n",FmtTime());
  391.     }
  392.     CheckDirTree(diskFd);
  393.     WriteSegCheckpoint(diskFd, checkPointPtr + sizeof(LfsCheckPointHdr),
  394.         &checkPointSize);
  395.  
  396.     checkPointHdrPtr->timestamp = ++currentTimestamp;
  397.     checkPointHdrPtr->size = checkPointSize + sizeof(LfsCheckPointHdr) + 
  398.              sizeof(LfsCheckPointTrailer);
  399.     checkPointHdrPtr->version = 1;
  400.     checkPointHdrPtr->detachSeconds = 0;
  401.     trailPtr = (LfsCheckPointTrailer *) 
  402.         (checkPointPtr + checkPointHdrPtr->size - 
  403.                 sizeof(LfsCheckPointTrailer));
  404.     trailPtr->timestamp = checkPointHdrPtr->timestamp;
  405.     trailPtr->checkSum = 0;
  406.  
  407.     /*
  408.      * Append the stats to the checkpoint regions.
  409.      */
  410.     bzero((char *) (trailPtr + 1), sizeof(Lfs_Stats));
  411.     if ( DiskWrite(diskFd, superBlockPtr->hdr.checkPointOffset[0], maxCheckPointSize, (char *) checkPointHdrPtr) != maxCheckPointSize) {
  412.     fprintf(stderr,"Can't write checkpoint region\n");
  413.     }
  414.     exit(EXIT_OK);
  415.     return EXIT_OK;
  416. }
  417.  
  418. /*
  419.  *----------------------------------------------------------------------
  420.  *
  421.  * AllocUsageArray --
  422.  *
  423.  *    Allocate memory for the segment usage array.
  424.  *
  425.  * Results:
  426.  *    TRUE if array can be allocated. FALSE otherwise.
  427.  *
  428.  * Side effects:
  429.  *    None.
  430.  *
  431.  *----------------------------------------------------------------------
  432.  */
  433.  
  434. Boolean
  435. AllocUsageArray()
  436. {
  437.     LfsSegUsageParams    *usagePtr;
  438.     LfsStableMemParams  *smemParamsPtr;
  439.     Boolean ret = TRUE;
  440.  
  441.     usagePtr = &(superBlockPtr->usageArray);
  442.     smemParamsPtr = &(superBlockPtr->usageArray.stableMem);
  443.  
  444.     usageCheckPointPtr =  (LfsSegUsageCheckPoint *) 
  445.             calloc(1, sizeof(LfsSegUsageCheckPoint));
  446.  
  447.  
  448.    usageArrayDataPtr =  AllocStableMem(smemParamsPtr, USAGE_ARRAY);
  449.    return ret;
  450. }
  451.  
  452.  
  453. /*
  454.  *----------------------------------------------------------------------
  455.  *
  456.  * AllocDescMap --
  457.  *
  458.  *    Allocate memory for the descriptor map array into memory.
  459.  *
  460.  * Results:
  461.  *    None.
  462.  *
  463.  * Side effects:
  464.  *    None.
  465.  *
  466.  *----------------------------------------------------------------------
  467.  */
  468. Boolean 
  469. AllocDescMap()
  470. {
  471.     LfsStableMemParams  *smemParamsPtr;
  472.     Boolean         ret = TRUE;
  473.  
  474.     smemParamsPtr = &(superBlockPtr->descMap.stableMem);
  475.  
  476.     descMapCheckPointPtr =  (LfsDescMapCheckPoint *) 
  477.                 calloc(1, sizeof(LfsDescMapCheckPoint));
  478.  
  479.     descMapDataPtr =  AllocStableMem(smemParamsPtr, DESC_MAP);
  480.  
  481.     return ret;
  482.  
  483. }
  484.  
  485. char *
  486. GetUsageState(entryPtr)
  487.     LfsSegUsageEntry *entryPtr;
  488. {
  489.     if (entryPtr->flags & LFS_SEG_USAGE_DIRTY) 
  490.     return "Dirty";
  491.     if (entryPtr->flags & LFS_SEG_USAGE_CLEAN) 
  492.     return "Clean";
  493.     return "Full";
  494. }
  495.  
  496. /*
  497.  *----------------------------------------------------------------------
  498.  *
  499.  * DiskRead --
  500.  *
  501.  *    Read data from disk.
  502.  *
  503.  * Results:
  504.  *    The number of bytes returned.  -1 if error.
  505.  *
  506.  * Side effects:
  507.  *    None.
  508.  *
  509.  *----------------------------------------------------------------------
  510.  */
  511. int
  512. DiskRead(diskFd, blockOffset, bufferSize, bufferPtr)
  513.     int    diskFd;        /* File descriptor of disk. */
  514.     int    blockOffset;    /* Block offset to start read. */
  515.     char *bufferPtr;    /* Buffer to place data. */
  516.     int     bufferSize;    /* Size of buffer. */
  517. {
  518.     int    status;
  519.     int    blocks;
  520.     char *bufPtr;
  521.  
  522.  
  523.     /*
  524.      * Seek to the start of the blocks to read.
  525.      */
  526.     status = lseek(diskFd, blockOffset*blockSize, L_SET);
  527.     if (status < 0) {
  528.     fprintf(stderr,"%s:", deviceName);
  529.     perror("lseek");
  530.     return status;
  531.     }
  532.     /*
  533.      * Read the blocks handling the case the a request that is not a 
  534.      * multiple number of blocks by reading to a temp buffer and copying.
  535.      */
  536.     blocks = (bufferSize + blockSize-1)/blockSize;
  537.     if (bufferSize != blocks * blockSize) { 
  538.     bufPtr = malloc(blocks*blockSize);
  539.     } else {
  540.     bufPtr = bufferPtr;
  541.     }
  542.     status = read(diskFd, bufPtr, blocks*blockSize);
  543.     if (status != blocks*blockSize) {
  544.     if (status < 0) {
  545.         fprintf(stderr,"%s:", deviceName);
  546.         perror("read device");
  547.         return status;
  548.     }
  549.     fprintf(stderr,"%s:Short read on device %d != %d\n",deviceName,
  550.         status, blocks*blockSize);
  551.     } else {
  552.     status = bufferSize;
  553.     }
  554.     if (bufPtr != bufferPtr) { 
  555.     bcopy(bufPtr, bufferPtr, bufferSize);
  556.     free(bufPtr);
  557.     }
  558.     return status;
  559. }
  560.  
  561.  
  562. /*
  563.  *----------------------------------------------------------------------
  564.  *
  565.  * DiskWrite --
  566.  *
  567.  *    Write data to the disk.
  568.  *
  569.  * Results:
  570.  *    The number of bytes returned.  -1 if error.
  571.  *
  572.  * Side effects:
  573.  *    None.
  574.  *
  575.  *----------------------------------------------------------------------
  576.  */
  577. int
  578. DiskWrite(diskFd, blockOffset, bufferSize, bufferPtr)
  579.     int    diskFd;        /* File descriptor of disk. */
  580.     int    blockOffset;    /* Block offset to start write. */
  581.     char *bufferPtr;    /* Buffer containing data to write */
  582.     int     bufferSize;    /* Size of buffer. */
  583. {
  584.     int    status;
  585.  
  586.     if (!doWrites) {
  587.     return bufferSize;
  588.     }
  589.     /*
  590.      * Seek to the start of the blocks to write.
  591.      */
  592.     status = lseek(diskFd, blockOffset*blockSize, L_SET);
  593.     if (status < 0) {
  594.     fprintf(stderr,"%s:", deviceName);
  595.     perror("lseek");
  596.     return status;
  597.     }
  598.     /*
  599.      * Writes the blocks
  600.      */
  601.     status = write(diskFd, bufferPtr, bufferSize);
  602.     if (status != bufferSize) {
  603.     if (status < 0) {
  604.         fprintf(stderr,"%s:", deviceName);
  605.         perror("read device");
  606.         return status;
  607.     }
  608.     fprintf(stderr,"%s:Short read on device %d != %d\n",deviceName,
  609.         status, bufferSize);
  610.     } 
  611.     return status;
  612. }
  613.  
  614. typedef struct StableMem {
  615.     LfsStableMemParams  *paramsPtr;  /* Parameters of stable memory. */
  616.     LfsStableMemCheckPoint *checkpointPtr;  /* Checkpoint pointer. */
  617.     int            *blockIndexPtr;        /* Block index of addresses. */
  618.     int            *dirtyBitMap;        /* Bitmap of dirty blocks. */
  619.     char        *dataPtr;        /* Data of stablemem */
  620.  
  621. } StableMem;
  622.  
  623. /*
  624.  *----------------------------------------------------------------------
  625.  *
  626.  * AllocStableMem --
  627.  *
  628.  *    Allocate a stable memory data structure
  629.  *
  630.  * Results:
  631.  *    A clientdata that can be used to access stable mem.
  632.  *
  633.  * Side effects:
  634.  *    None.
  635.  *
  636.  *----------------------------------------------------------------------
  637.  */
  638. static ClientData 
  639. AllocStableMem(smemParamsPtr, type)
  640.     LfsStableMemParams  *smemParamsPtr;  /* Parameters of stable memory. */
  641.     int        type;
  642. {
  643.     int arraySize;
  644.     int *blockIndexPtr;
  645.     StableMem *stableMemPtr;
  646.  
  647.     arraySize = smemParamsPtr->blockSize * smemParamsPtr->maxNumBlocks;
  648.     stableMemPtr = (StableMem *) malloc(sizeof(StableMem));
  649.     stableMemPtr->paramsPtr = smemParamsPtr;
  650.     stableMemPtr->checkpointPtr = 
  651.     (LfsStableMemCheckPoint *) calloc(1, sizeof(LfsStableMemCheckPoint));
  652.     blockIndexPtr = (int *) calloc(smemParamsPtr->maxNumBlocks, sizeof(int));
  653.     stableMemPtr->blockIndexPtr = blockIndexPtr;
  654.     Bit_Alloc(smemParamsPtr->maxNumBlocks, stableMemPtr->dirtyBitMap);
  655.     stableMemPtr->dataPtr = calloc(1, arraySize);
  656.     return (ClientData) stableMemPtr;
  657. }
  658. char *
  659. GetStableMemEntry(clientData, entryNumber)
  660.     ClientData clientData;
  661.     int entryNumber;
  662. {
  663.     StableMem *stableMemPtr = (StableMem *) clientData;
  664.     int blockNum, offset;
  665.  
  666.     if ((entryNumber < 0) || 
  667.     (entryNumber >= stableMemPtr->paramsPtr->maxNumEntries)) {
  668.     fprintf(stderr,"Bad stable memory entry number %d\n", entryNumber);
  669.     entryNumber = 0;
  670.     }
  671.     blockNum = entryNumber / stableMemPtr->paramsPtr->entriesPerBlock;
  672.     offset = (entryNumber % stableMemPtr->paramsPtr->entriesPerBlock) * 
  673.         stableMemPtr->paramsPtr->entrySize + 
  674.            sizeof(LfsStableMemBlockHdr);
  675.     Bit_Set(blockNum, stableMemPtr->dirtyBitMap);
  676.     return stableMemPtr->dataPtr + 
  677.         blockNum * stableMemPtr->paramsPtr-> blockSize + offset;
  678. }
  679. static void
  680. SetStableMemBlockIndex(clientData, blockNum, address)
  681.     ClientData clientData;
  682.     int blockNum;
  683.     int address;
  684. {
  685.     StableMem *stableMemPtr = (StableMem *) clientData;
  686.  
  687.     if ((blockNum < 0) || 
  688.     (blockNum >= stableMemPtr->paramsPtr->maxNumBlocks)) {
  689.     fprintf(stderr,"Bad stable memory block num %d\n", blockNum);
  690.     return;
  691.     }
  692.     stableMemPtr->blockIndexPtr[blockNum] = address;
  693.     return;
  694. }
  695. Boolean
  696. StableMemCheckpoint(clientData, segPtr, checkPointPtr, checkPointSizePtr)
  697.     ClientData clientData;
  698.     LfsSeg    *segPtr;
  699.     char    *checkPointPtr;
  700.     int        *checkPointSizePtr;
  701. {
  702.     StableMem *stableMemPtr = (StableMem *) clientData;
  703.     LfsStableMemBlockHdr *hdrPtr;
  704.     LfsStableMemCheckPoint    checkPoint;
  705.     LfsSegElement    *bufferPtr;
  706.     int blockNum, offset, blockSize, fsBlocks;
  707.     char    *summaryPtr;
  708.  
  709.     offset = 0;
  710.     blockSize = stableMemPtr->paramsPtr-> blockSize;
  711.     fsBlocks = blockSize/superBlockPtr->hdr.blockSize;
  712.  
  713.     checkPoint.numBlocks = 0;
  714.     while ( (blockNum = Bit_FindFirstSet(
  715.                stableMemPtr->paramsPtr->maxNumBlocks,
  716.                stableMemPtr->dirtyBitMap)) != -1) {
  717.     char *dataPtr = stableMemPtr->dataPtr + blockNum * blockSize;
  718.     if (IsZero(dataPtr, blockSize)) {
  719.         SetStableMemBlockIndex(clientData,blockNum, FSDM_NIL_INDEX);
  720.         Bit_Clear(blockNum, stableMemPtr->dirtyBitMap);
  721.         continue;
  722.     }
  723.     summaryPtr = LfsSegGrowSummary(segPtr, fsBlocks, sizeof(int));
  724.     if (summaryPtr == (char *)NIL) {
  725.         return TRUE;
  726.     }
  727.     hdrPtr = (LfsStableMemBlockHdr *) dataPtr;
  728.     hdrPtr->magic = LFS_STABLE_MEM_BLOCK_MAGIC;
  729.     hdrPtr->memType = stableMemPtr->paramsPtr->memType;
  730.     hdrPtr->blockNum = blockNum;
  731.     hdrPtr->reserved = 0;
  732.  
  733.     bufferPtr = LfsSegAddDataBuffer(segPtr, fsBlocks, dataPtr, 
  734.                 (ClientData)NIL);
  735.     *(int *)summaryPtr = blockNum;
  736.     LfsSegSetSummaryPtr(segPtr,summaryPtr + sizeof(int));
  737.     SetStableMemBlockIndex(clientData, blockNum, 
  738.                 LfsSegDiskAddress(segPtr, bufferPtr));
  739.     segPtr->activeBytes += blockSize;
  740.     Bit_Clear(blockNum, stableMemPtr->dirtyBitMap);
  741.     if (blockNum >= checkPoint.numBlocks) {
  742.         checkPoint.numBlocks = blockNum+1;
  743.     }
  744.     }
  745.     *(LfsStableMemCheckPoint *) checkPointPtr = checkPoint;
  746.     bcopy((char *) stableMemPtr->blockIndexPtr, 
  747.         checkPointPtr + sizeof(LfsStableMemCheckPoint), 
  748.         sizeof(int) * checkPoint.numBlocks);
  749.     *checkPointSizePtr = sizeof(int) * checkPoint.numBlocks + 
  750.                 sizeof(LfsStableMemCheckPoint);
  751.  
  752.     return FALSE;
  753. }
  754. Boolean
  755. LfsSegUsageCheckpoint(segPtr, checkPointPtr, checkPointSizePtr)
  756.     LfsSeg *segPtr;        /* Segment containing data for checkpoint. */
  757.     char   *checkPointPtr;      /* Buffer to write checkpoint data. */
  758.     int       *checkPointSizePtr;  /* Bytes added to the checkpoint area.*/
  759. {
  760.     LfsSegUsageCheckPoint *cp = (LfsSegUsageCheckPoint *) checkPointPtr;
  761.     int        size;
  762.     Boolean    full;
  763.  
  764.     *cp = *usageCheckPointPtr;
  765.     size = sizeof(LfsSegUsageCheckPoint);
  766.  
  767.     full = StableMemCheckpoint(usageArrayDataPtr, segPtr, checkPointPtr + size,
  768.         checkPointSizePtr);
  769.     if (!full) { 
  770.     *checkPointSizePtr = (*checkPointSizePtr) + size;
  771.     }
  772.     return full;
  773.  
  774. }
  775.  
  776. /*
  777.  *----------------------------------------------------------------------
  778.  *
  779.  * DescMapCheckpoint --
  780.  *
  781.  *    Routine to handle checkpointing of the descriptor map data.
  782.  *
  783.  * Results:
  784.  *    TRUE if more data needs to be written, FALSE if this module is
  785.  *    checkpointed.
  786.  *
  787.  * Side effects:
  788.  *    Many
  789.  *
  790.  *----------------------------------------------------------------------
  791.  */
  792.  
  793. Boolean
  794. LfsDescMapCheckpoint(segPtr, checkPointPtr, checkPointSizePtr)
  795.     LfsSeg *segPtr;        /* Segment containing data for checkpoint. */
  796.     char   *checkPointPtr;      /* Buffer to write checkpoint data. */
  797.     int       *checkPointSizePtr;  /* Bytes added to the checkpoint area.*/
  798. {
  799.     LfsDescMapCheckPoint *cp = (LfsDescMapCheckPoint *) checkPointPtr;
  800.     int        size, dataSize;
  801.     Boolean    full;
  802.  
  803.     *cp = *descMapCheckPointPtr;
  804.     size = sizeof(LfsDescMapCheckPoint);
  805.     dataSize = 0;
  806.     full = StableMemCheckpoint(descMapDataPtr, segPtr, checkPointPtr + size, 
  807.             &dataSize);
  808.     if (!full) { 
  809.     (*checkPointSizePtr) = dataSize + size;
  810.     }
  811.     return full;
  812.  
  813. }
  814.  
  815.  
  816. /*
  817.  *----------------------------------------------------------------------
  818.  *
  819.  * FindAllFiles --
  820.  *
  821.  *    Check all the files in the system.
  822.  *
  823.  * Results:
  824.  *    None.
  825.  *
  826.  * Side effects:
  827.  *    None.
  828.  *
  829.  *----------------------------------------------------------------------
  830.  */
  831. static void
  832. FindAllFiles(diskFd)
  833.     int diskFd;
  834. {
  835.     LfsFileDescriptor    *descPtr;
  836.     char *descBuf;
  837.     LfsDescMapEntry *descMapPtr;
  838.     int bufSize, i, j;
  839.  
  840.     bufSize = superBlockPtr->fileLayout.descPerBlock * sizeof(*descPtr);
  841.  
  842.     descBuf = alloca(bufSize);
  843.     descMapPtr = DescMapEntry(0);
  844.     descMapPtr->flags = LFS_DESC_MAP_ALLOCED;
  845.     descMapCheckPointPtr->numAllocDesc++;
  846.     descMapPtr = DescMapEntry(1);
  847.     descMapPtr->flags = LFS_DESC_MAP_ALLOCED;
  848.     descMapCheckPointPtr->numAllocDesc++;
  849.     descInfoArray[0].flags = descInfoArray[1].flags = FD_UNREADABLE;
  850.  
  851.     for (i = 2; i < superBlockPtr->descMap.maxDesc; i++) {
  852.     if ((descInfoArray[i].flags & FD_ALLOCATED) == 0) {
  853.         continue;
  854.     }
  855.     if (DiskRead(diskFd, descInfoArray[i].addr, bufSize, descBuf)
  856.             != bufSize) {
  857.         majorErrors++;
  858.         fprintf(stderr,"%s:FindAllFiles: Can't read desc for file %d\n",
  859.                 deviceName,i);
  860.     }
  861.     descPtr = (LfsFileDescriptor *)descBuf;
  862.     for (j = 0; j < superBlockPtr->fileLayout.descPerBlock; j++) {
  863.         if (!(descPtr->common.flags & FSDM_FD_ALLOC)) {
  864.         break;
  865.         }
  866.         if (descPtr->common.magic != FSDM_FD_MAGIC) {
  867.         majorErrors++;
  868.         fprintf(stderr,"%s:FindAllFiles: Corrupted descriptor block at %d, magic number 0x%x\n", deviceName, descMapPtr->blockAddress, descPtr->common.magic);
  869.         }
  870.         if (descPtr->fileNumber == i) {
  871.         break;
  872.         }
  873.         descPtr++;
  874.     }
  875.     if ((j >= superBlockPtr->fileLayout.descPerBlock) ||
  876.         !(descPtr->common.flags & FSDM_FD_ALLOC) ||
  877.         (descPtr->fileNumber != i)) {
  878.         majorErrors++;
  879.         fprintf(stderr,"%s:FindAllFiles: Can't desc for file %d at %d\n",
  880.             deviceName,i, descMapPtr->blockAddress);
  881.         descInfoArray[i].flags = FD_UNREADABLE;
  882.         continue;
  883.     } 
  884.     if (!CheckFile(diskFd, i, descPtr)) {
  885.         descInfoArray[i].flags = FD_UNREADABLE;
  886.         continue;
  887.     }
  888.     descMapPtr = DescMapEntry(i);
  889.     descMapPtr->blockAddress = descInfoArray[i].addr;
  890.     descMapPtr->flags = LFS_DESC_MAP_ALLOCED;
  891.     descMapPtr->truncVersion = descInfoArray[i].truncVersion;
  892.     descMapCheckPointPtr->numAllocDesc++;
  893.     descInfoArray[i].origLinkCount = descPtr->common.numLinks;
  894.     if (shownew) {
  895.         printf("Desc %d blockAddress %d\n", i , descMapPtr->blockAddress);
  896.     }
  897.     }
  898. }
  899.  
  900. /*
  901.  *----------------------------------------------------------------------
  902.  *
  903.  * ComputeUsageArray --
  904.  *
  905.  *    Check all the files in the and build the correct segment usage
  906.  *    array.
  907.  *
  908.  * Results:
  909.  *    None.
  910.  *
  911.  * Side effects:
  912.  *    None.
  913.  *
  914.  *----------------------------------------------------------------------
  915.  */
  916. static void
  917. ComputeUsageArray(diskFd)
  918.     int diskFd;
  919. {
  920.     LfsFileDescriptor    *descPtr;
  921.     char *descBuf;
  922.     LfsDescMapEntry *descMapPtr;
  923.     int bufSize, i, j;
  924.  
  925.     computeUsageArray = TRUE;
  926.  
  927.     bufSize = superBlockPtr->fileLayout.descPerBlock * sizeof(*descPtr);
  928.     descBuf = alloca(bufSize);
  929.  
  930.     for (i = 2; i < superBlockPtr->descMap.maxDesc; i++) {
  931.     descMapPtr = DescMapEntry(i);
  932.     if (!(descMapPtr->flags & LFS_DESC_MAP_ALLOCED)) {
  933.         continue;
  934.     }
  935.     if (DiskRead(diskFd, descMapPtr->blockAddress, bufSize, descBuf)
  936.             != bufSize) {
  937.         majorErrors++;
  938.         fprintf(stderr,"%s:FindAllFiles: Can't read desc for file %d\n",
  939.                 deviceName,i);
  940.     }
  941.     descPtr = (LfsFileDescriptor *)descBuf;
  942.     for (j = 0; j < superBlockPtr->fileLayout.descPerBlock; j++) {
  943.         if (!(descPtr->common.flags & FSDM_FD_ALLOC)) {
  944.         break;
  945.         }
  946.         if (descPtr->common.magic != FSDM_FD_MAGIC) {
  947.         majorErrors++;
  948.         fprintf(stderr,"%s:FindAllFiles: Corrupted descriptor block at %d, magic number 0x%x\n", deviceName, descMapPtr->blockAddress, descPtr->common.magic);
  949.         }
  950.         if (descPtr->fileNumber == i) {
  951.         break;
  952.         }
  953.         descPtr++;
  954.     }
  955.     if ((j >= superBlockPtr->fileLayout.descPerBlock) ||
  956.         !(descPtr->common.flags & FSDM_FD_ALLOC) ||
  957.         (descPtr->fileNumber != i)) {
  958.         majorErrors++;
  959.         fprintf(stderr,"%s:FindAllFiles: Can't desc for file %d at %d\n",
  960.             deviceName,i, descMapPtr->blockAddress);
  961.         continue;
  962.     } 
  963.     CheckFile(diskFd, i, descPtr);
  964.     activeBytesArray[BlockToSegmentNum(descMapPtr->blockAddress)] +=
  965.                     sizeof(LfsFileDescriptor);
  966.     }
  967. }
  968.  
  969. /*
  970.  *----------------------------------------------------------------------
  971.  *
  972.  * CheckFile --
  973.  *
  974.  *    Check a file in the system.
  975.  *
  976.  * Results:
  977.  *    None.
  978.  *
  979.  * Side effects:
  980.  *    None.
  981.  *
  982.  *----------------------------------------------------------------------
  983.  */
  984. static Boolean
  985. CheckFile(diskFd, fileNum, descPtr) 
  986.     int diskFd;
  987.     int fileNum;
  988.     LfsFileDescriptor *descPtr;
  989. {
  990.     int i;
  991.     Boolean good;
  992.  
  993.     for (i = 0; i < FSDM_NUM_DIRECT_BLOCKS; i++) {
  994.     if (descPtr->common.direct[i] != FSDM_NIL_INDEX) {
  995.         if (i * FS_BLOCK_SIZE > descPtr->common.lastByte + 1) {
  996.         majorErrors++;
  997.         fprintf(stderr, 
  998.         "%s:CheckFile: File %d has a non-NIL block %d after lastByte %d.\n",
  999.             deviceName,fileNum, i, descPtr->common.lastByte);
  1000.         return FALSE;
  1001.          continue;
  1002.         }
  1003.         good = CheckBlock(diskFd, fileNum, descPtr, i, descPtr->common.direct[i]);
  1004.         if (!good) {
  1005.         return FALSE;
  1006.         }
  1007.     }
  1008.     }
  1009.     if (descPtr->common.indirect[0] != FSDM_NIL_INDEX) { 
  1010.         if (FSDM_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE > 
  1011.             descPtr->common.lastByte + 1) {
  1012.         majorErrors++;
  1013.         fprintf(stderr, 
  1014.         "%s:CheckFile: File %d has a non-NIL block %d after lastByte %d.\n",
  1015.             deviceName,fileNum, -1, descPtr->common.lastByte);
  1016.         return FALSE;
  1017.         }
  1018.         good = CheckIndirectBlock(diskFd, fileNum, descPtr, -1,
  1019.                 descPtr->common.indirect[0]);
  1020.         if (!good) {
  1021.         return FALSE;
  1022.         }
  1023.     }
  1024.     if (descPtr->common.indirect[1] != FSDM_NIL_INDEX) { 
  1025.         if (FSDM_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE + 
  1026.             FS_BLOCK_SIZE * FS_BLOCK_SIZE/4 > 
  1027.             descPtr->common.lastByte + 1) {
  1028.         majorErrors++;
  1029.         fprintf(stderr, 
  1030.     "%s:CheckFile: File %d has a non-NIL block %d after lastByte %d.\n",
  1031.             deviceName, fileNum, -2, descPtr->common.lastByte);
  1032.         return FALSE;
  1033.         }
  1034.         good = CheckIndirectBlock(diskFd, fileNum, descPtr, -2, 
  1035.                 descPtr->common.indirect[1]);
  1036.         if (!good) {
  1037.         return FALSE;
  1038.         }
  1039.     }
  1040.     if (descPtr->common.indirect[2] != FSDM_NIL_INDEX) { 
  1041.         majorErrors++;
  1042.         fprintf(stderr, 
  1043.     "%s:CheckFile: File %d has a non-NIL block %d after lastByte %d.\n",
  1044.             deviceName, fileNum, -3, descPtr->common.lastByte);
  1045.     return FALSE;
  1046.     }
  1047.     return TRUE;
  1048. }
  1049.  
  1050.  
  1051. /*
  1052.  *----------------------------------------------------------------------
  1053.  *
  1054.  * CheckIndirectBlock --
  1055.  *
  1056.  *    Check an indirect block of a file..
  1057.  *
  1058.  * Results:
  1059.  *    None.
  1060.  *
  1061.  * Side effects:
  1062.  *    None.
  1063.  *
  1064.  *----------------------------------------------------------------------
  1065.  */
  1066.  
  1067. static Boolean
  1068. CheckIndirectBlock(diskFd, fileNum, descPtr, blockNum, blockAddress)
  1069.     int diskFd;
  1070.     int fileNum;
  1071.     LfsFileDescriptor *descPtr;
  1072.     int blockNum;
  1073.     int    blockAddress;
  1074. {
  1075.     int  i;
  1076.     int blockPtrs[FS_BLOCK_SIZE/4];
  1077.     Boolean good;
  1078.  
  1079.  
  1080.  
  1081.     good = CheckBlock(diskFd, fileNum, descPtr, blockNum, blockAddress);
  1082.     if (!good) {
  1083.     return FALSE;
  1084.     }
  1085.     if (DiskRead(diskFd, blockAddress, FS_BLOCK_SIZE, (char *)blockPtrs)
  1086.         != FS_BLOCK_SIZE) {
  1087.     majorErrors++;
  1088.     fprintf(stderr,"%s:CheckIndirectBlock: Can't read block %d of file %d.\n",
  1089.                 deviceName, blockNum, fileNum);
  1090.     return FALSE;
  1091.  
  1092.     }
  1093.     if ((blockNum == -1) || (blockNum < -3)) { 
  1094.     int start;
  1095.     if (blockNum == -1) {
  1096.         start = FSDM_NUM_DIRECT_BLOCKS;
  1097.     } else {
  1098.         start = FSDM_NUM_DIRECT_BLOCKS + (FS_BLOCK_SIZE/4) + 
  1099.                  (FS_BLOCK_SIZE/4) * 
  1100.                  (-blockNum - (FSDM_NUM_INDIRECT_BLOCKS+1));
  1101.     }
  1102.     for (i = 0; i < FS_BLOCK_SIZE/4; i++) {
  1103.         if (blockPtrs[i] != FSDM_NIL_INDEX) { 
  1104.         good = CheckBlock(diskFd, fileNum, descPtr,
  1105.                start + i,blockPtrs[i]);
  1106.         if (!good) {
  1107.           return FALSE;
  1108.         }
  1109.         }
  1110.     }
  1111.     return TRUE;
  1112.     } 
  1113.     if (blockNum == -2) {
  1114.     for (i = 0; i < FS_BLOCK_SIZE/4; i++) {
  1115.         if (blockPtrs[i] != FSDM_NIL_INDEX) { 
  1116.         good = CheckIndirectBlock(diskFd, fileNum, descPtr,
  1117.                 - i  - (FSDM_NUM_INDIRECT_BLOCKS+1),blockPtrs[i]);
  1118.         if (!good) {
  1119.           return FALSE;
  1120.         }
  1121.         }
  1122.     }
  1123.     return TRUE;
  1124.     }
  1125.     majorErrors++;
  1126.     fprintf(stderr,"%s:CheckIndirectBlock: Bad block number %d for file %d\n",
  1127.             deviceName, blockNum, fileNum);
  1128.     return FALSE;
  1129. }
  1130.  
  1131.  
  1132. /*
  1133.  *----------------------------------------------------------------------
  1134.  *
  1135.  * CheckFile --
  1136.  *
  1137.  *    Check a block of a file.
  1138.  *
  1139.  * Results:
  1140.  *    None.
  1141.  *
  1142.  * Side effects:
  1143.  *    None.
  1144.  *
  1145.  *----------------------------------------------------------------------
  1146.  */
  1147. static Boolean
  1148. CheckBlock(diskFd, fileNum, descPtr, blockNum, blockAddress)
  1149.     int diskFd;
  1150.     int fileNum;
  1151.     LfsFileDescriptor *descPtr;
  1152.     int blockNum;
  1153.     int    blockAddress;
  1154. {
  1155.     int j;
  1156.     int sizeInBlocks;
  1157.  
  1158.  
  1159.     sizeInBlocks = FS_BLOCK_SIZE/blockSize;
  1160.     if (blockNum >= 0) { 
  1161.     if ((blockNum+1) * FS_BLOCK_SIZE > descPtr->common.lastByte + 1) {
  1162.         int size;
  1163.         size = descPtr->common.lastByte - FS_BLOCK_SIZE*blockNum +  1;
  1164.          sizeInBlocks = (size + blockSize - 1)/blockSize;
  1165.      }
  1166.     }
  1167.  
  1168.     if ((blockAddress < 0) || 
  1169.     (blockAddress+sizeInBlocks > numBlocks)) {
  1170.     majorErrors++;
  1171.     fprintf(stderr, "%s:CheckFile: file %d block %d is out of range %d\n",
  1172.         deviceName, fileNum, blockNum, blockAddress);
  1173.     return FALSE;
  1174.     }
  1175.     for (j = 0; j < sizeInBlocks; j++) {
  1176.     if ((blockInfoArray[blockAddress + j].type != FILE) &&
  1177.         (blockInfoArray[blockAddress + j].fileNum != fileNum) &&
  1178.         (blockInfoArray[blockAddress + j].blockNum != blockNum) &&
  1179.         !SAME_VERSION(descInfoArray[fileNum].truncVersion, blockInfoArray[blockAddress + j])) {
  1180.         majorErrors++;
  1181.         fprintf(stderr, 
  1182.         "%s:CheckFile:file %d block %d duplicate usage of block %d ",
  1183.             deviceName,
  1184.  
  1185.             fileNum, blockNum, blockAddress + j);
  1186.         fprintf(stderr,"Previous use at %s\n", 
  1187.                 GetOwner(blockAddress + j));
  1188.         return FALSE;
  1189.     } 
  1190.     }
  1191.     if (computeUsageArray) { 
  1192.     activeBytesArray[BlockToSegmentNum(blockAddress)] 
  1193.             += blockSize*sizeInBlocks;
  1194.     }
  1195.     return TRUE;
  1196. }
  1197.  
  1198. /*
  1199.  *----------------------------------------------------------------------
  1200.  *
  1201.  * BuildUsageArray --
  1202.  *
  1203.  *    Build the segment usage array.
  1204.  *
  1205.  * Results:
  1206.  *    None.
  1207.  *
  1208.  * Side effects:
  1209.  *    None.
  1210.  *
  1211.  *----------------------------------------------------------------------
  1212.  */
  1213. static void
  1214. BuildUsageArray(diskFd)
  1215. int diskFd;
  1216. {
  1217.     int segNo;
  1218.     Boolean foundCurrent;
  1219.     LfsSegUsageEntry *usageArrayPtr;
  1220.  
  1221.     usageCheckPointPtr->freeBlocks = 0;  
  1222.     usageCheckPointPtr->numClean = 0;
  1223.     usageCheckPointPtr->numDirty = 0;
  1224.     usageCheckPointPtr->dirtyActiveBytes = 
  1225.             (int) (superBlockPtr->usageArray.segmentSize * .90);
  1226.     usageCheckPointPtr->currentSegment = 0;
  1227.     usageCheckPointPtr->currentBlockOffset = -1;
  1228.     usageCheckPointPtr->curSegActiveBytes = 0;
  1229.     usageCheckPointPtr->previousSegment = -1;
  1230.     usageCheckPointPtr->cleanSegList = -1;
  1231.     foundCurrent = FALSE;
  1232.     for (segNo = 0; segNo < superBlockPtr->usageArray.numberSegments; 
  1233.     segNo++) {
  1234.     usageArrayPtr = UsageArrayEntry(segNo);
  1235.     if (activeBytesArray[segNo] == 0) {
  1236.         usageArrayPtr->flags = LFS_SEG_USAGE_CLEAN;
  1237.         usageArrayPtr->activeBytes = usageCheckPointPtr->cleanSegList;
  1238.         usageCheckPointPtr->cleanSegList = segNo;
  1239.         usageCheckPointPtr->numClean++;
  1240.         usageCheckPointPtr->freeBlocks += 
  1241.             superBlockPtr->usageArray.segmentSize/blockSize;
  1242.     } else if (activeBytesArray[segNo] <
  1243.                 usageCheckPointPtr->dirtyActiveBytes) {
  1244.         if (!foundCurrent) { 
  1245.         usageArrayPtr->activeBytes = 0;
  1246.         usageArrayPtr->flags = 0;
  1247.         usageCheckPointPtr->currentSegment = segNo;
  1248.         usageCheckPointPtr->curSegActiveBytes = 
  1249.                 activeBytesArray[segNo];
  1250.  
  1251.         usageArrayPtr->activeBytes  = 0;
  1252.         foundCurrent = TRUE;
  1253.         } else { 
  1254.         usageArrayPtr->activeBytes = activeBytesArray[segNo];
  1255.         usageArrayPtr->flags = LFS_SEG_USAGE_DIRTY;
  1256.         usageCheckPointPtr->numDirty++;
  1257.         usageCheckPointPtr->freeBlocks += 
  1258.             (superBlockPtr->usageArray.segmentSize - 
  1259.             usageArrayPtr->activeBytes + blockSize - 1)/blockSize;
  1260.         }
  1261.     } else {
  1262.         usageArrayPtr->flags = 0;
  1263.         if (!foundCurrent) { 
  1264.         usageArrayPtr->activeBytes = 0;
  1265.         usageCheckPointPtr->currentSegment = segNo;
  1266.         usageCheckPointPtr->curSegActiveBytes = 
  1267.                 activeBytesArray[segNo];
  1268.         foundCurrent = TRUE;
  1269.         } else {
  1270.         usageArrayPtr->activeBytes = activeBytesArray[segNo];
  1271.         usageCheckPointPtr->freeBlocks += 
  1272.             (superBlockPtr->usageArray.segmentSize - 
  1273.             usageArrayPtr->activeBytes + blockSize - 1)/blockSize;
  1274.         }
  1275.     }
  1276.     if (shownew) {
  1277.         printf("Seg %d flag %d activeBytes %d\n", segNo,
  1278.             usageArrayPtr->flags,
  1279.             usageArrayPtr->activeBytes);
  1280.     }
  1281.     }
  1282. }
  1283.  
  1284.  
  1285. /*
  1286.  *----------------------------------------------------------------------
  1287.  *
  1288.  * LfsGetLogTail --
  1289.  *
  1290.  *    Get the next available clean blocks to write the log to.
  1291.  *
  1292.  * Results:
  1293.  *    SUCCESS if log space was retrieved. FS_NO_DISK_SPACE if log
  1294.  *    space is not available. FS_WOULD_BLOCK if operation of blocked.
  1295.  *
  1296.  * Side effects:
  1297.  *
  1298.  *
  1299.  *----------------------------------------------------------------------
  1300.  */
  1301.  
  1302. ReturnStatus
  1303. LfsGetLogTail(logRangePtr, startBlockPtr)
  1304.     LfsSegLogRange *logRangePtr;  /* Segments numbers returned. */
  1305.     int           *startBlockPtr; /* OUT: Starting offset into segment. */
  1306. {
  1307.     LfsSegUsageEntry *s;
  1308.     int        segNumber;
  1309.  
  1310.     if (usageCheckPointPtr->currentBlockOffset != -1) {
  1311.     /*
  1312.      * There is still room in the existing segment. Use it.
  1313.      */
  1314.     logRangePtr->prevSeg = usageCheckPointPtr->previousSegment;
  1315.     logRangePtr->current = usageCheckPointPtr->currentSegment;
  1316.     logRangePtr->nextSeg =  usageCheckPointPtr->cleanSegList;
  1317.     (*startBlockPtr) = usageCheckPointPtr->currentBlockOffset;
  1318.     return SUCCESS;
  1319.     }
  1320.     /*
  1321.      * Need to location a new segment.
  1322.      */
  1323.     if (usageCheckPointPtr->numClean == 0) {
  1324.     fprintf(stderr, "No clean segments to write\n");
  1325.     return FS_NO_DISK_SPACE;
  1326.     }
  1327.     s = UsageArrayEntry( usageCheckPointPtr->currentSegment);
  1328.     s->activeBytes = usageCheckPointPtr->curSegActiveBytes;
  1329.     usageCheckPointPtr->freeBlocks += 
  1330.             (superBlockPtr->usageArray.segmentSize - 
  1331.             s->activeBytes + blockSize - 1)/blockSize;
  1332.     if (s->activeBytes <= usageCheckPointPtr->dirtyActiveBytes) {
  1333.     s->flags |= LFS_SEG_USAGE_DIRTY;
  1334.     usageCheckPointPtr->numDirty++;
  1335.     }
  1336.     s->timeOfLastWrite = 2;
  1337.     segNumber = usageCheckPointPtr->cleanSegList;
  1338.     s = UsageArrayEntry(segNumber);
  1339.     usageCheckPointPtr->cleanSegList = s->activeBytes;
  1340.  
  1341.     logRangePtr->prevSeg = usageCheckPointPtr->previousSegment = usageCheckPointPtr->currentSegment;
  1342.     logRangePtr->current = usageCheckPointPtr->currentSegment = segNumber;
  1343.     logRangePtr->nextSeg =  usageCheckPointPtr->cleanSegList;
  1344.  
  1345.     usageCheckPointPtr->numClean--;
  1346.     s->activeBytes = usageCheckPointPtr->curSegActiveBytes = 0;
  1347.     s->flags  &= ~LFS_SEG_USAGE_CLEAN;
  1348.     (*startBlockPtr) = 0;
  1349.     return SUCCESS;
  1350. }
  1351.  
  1352. /*
  1353.  *----------------------------------------------------------------------
  1354.  *
  1355.  * LfsSetLogTail --
  1356.  *
  1357.  *    Set the next available clean blocks to write the log to.
  1358.  *
  1359.  * Results:
  1360.  *    None
  1361.  *
  1362.  * Side effects:
  1363.  *
  1364.  *
  1365.  *----------------------------------------------------------------------
  1366.  */
  1367.  
  1368. void
  1369. LfsSetLogTail( logRangePtr, startBlock, activeBytes)
  1370.     LfsSegLogRange *logRangePtr;  /* Segments numbers. */
  1371.     int    startBlock; /* Starting offset into segment. */
  1372.     int    activeBytes;    /* Number of bytes written. */
  1373. {
  1374.     usageCheckPointPtr->currentBlockOffset = startBlock;
  1375.     if (activeBytes > 0) {
  1376.     usageCheckPointPtr->curSegActiveBytes += activeBytes;
  1377.     usageCheckPointPtr->freeBlocks -= 
  1378.             (activeBytes + blockSize - 1)/blockSize;
  1379.    }
  1380. }
  1381.  
  1382.  
  1383. /*
  1384.  *----------------------------------------------------------------------
  1385.  *
  1386.  * LfsSegUsageCheckpointUpdate --
  1387.  *
  1388.  *    This routine is used to update fields of the seg usage 
  1389.  *    checkpoint that change when the checkpoint itself is 
  1390.  *    written to the log.
  1391.  *
  1392.  * Results:
  1393.  *    None.
  1394.  *
  1395.  * Side effects:
  1396.  *    None.
  1397.  *
  1398.  *----------------------------------------------------------------------
  1399.  */
  1400.  
  1401. void
  1402. LfsSegUsageCheckpointUpdate(checkPointPtr, size)
  1403.     char *checkPointPtr; /* Checkpoint region for SegUsage. */
  1404.     int     size;         /* Size of checkpoint region. */
  1405. {
  1406.  
  1407.     (*(LfsSegUsageCheckPoint *) checkPointPtr) = *usageCheckPointPtr;
  1408.     return;
  1409. }
  1410.  
  1411.  
  1412.  
  1413. /*
  1414.  *----------------------------------------------------------------------
  1415.  *
  1416.  * CheckSummaryRegions --
  1417.  *
  1418.  *    Check the segment summary regions.
  1419.  *
  1420.  * Results:
  1421.  *    None.
  1422.  *
  1423.  * Side effects:
  1424.  *    None.
  1425.  *
  1426.  *----------------------------------------------------------------------
  1427.  */
  1428. static void
  1429. CheckSummaryRegions(diskFd)
  1430. int diskFd;
  1431. {
  1432.     int segNo, startAddr, blockOffset;
  1433.     char *summaryLimitPtr, *summaryPtr;
  1434.     LfsSegSummary *segSummaryPtr;
  1435.     LfsSegSummaryHdr *segSummaryHdrPtr;
  1436.     Seg    *segPtr;
  1437.  
  1438.     for (segNo = 0; segNo < superBlockPtr->usageArray.numberSegments; 
  1439.     segNo++) {
  1440.     segPtr = SegInit(diskFd, segNo);
  1441.     startAddr = SegStartAddr(segPtr) + segPtr->segSizeInBlocks;
  1442.     blockOffset = 1; 
  1443.     do { 
  1444.         segSummaryPtr = (LfsSegSummary *) 
  1445.             SegFetchBlock(segPtr, blockOffset-1, blockSize);
  1446.         if (segSummaryPtr->size == 0) {
  1447.         SegReleaseBlock(segPtr, (char *) segSummaryPtr);
  1448.         break;
  1449.         }
  1450.         if (segSummaryPtr->magic != LFS_SEG_SUMMARY_MAGIC) {
  1451.         majorErrors++;
  1452.         fprintf(stderr,"%s: Bad magic number 0x%x for summary region of segment %d\n", deviceName, segSummaryPtr->magic, segNo);
  1453.         SegReleaseBlock(segPtr, (char *) segSummaryPtr);
  1454.         break;
  1455.         }
  1456.         if (segSummaryPtr->timestamp >= currentTimestamp) {
  1457.         currentTimestamp = segSummaryPtr->timestamp + 1;
  1458.         }
  1459.         summaryLimitPtr = (char *) segSummaryPtr + segSummaryPtr->size;
  1460.         summaryPtr = (char *) (segSummaryPtr + 1);
  1461.         while (summaryPtr < summaryLimitPtr) {
  1462.            segSummaryHdrPtr = (LfsSegSummaryHdr *) summaryPtr;
  1463.            if (segSummaryHdrPtr->lengthInBytes == 0) {
  1464.             break;
  1465.            }
  1466.            switch (segSummaryHdrPtr->moduleType) { 
  1467.            case LFS_SEG_USAGE_MOD:
  1468.           CheckSegUsageSummary(diskFd, segPtr, 
  1469.                 segSummaryPtr->timestamp, 
  1470.                 startAddr - blockOffset, 
  1471.                 blockOffset, segSummaryHdrPtr);
  1472.            break;
  1473.            case LFS_DESC_MAP_MOD:
  1474.           CheckDescMapSummary(diskFd, segPtr, 
  1475.                 segSummaryPtr->timestamp, 
  1476.                 startAddr - blockOffset, blockOffset, 
  1477.                 segSummaryHdrPtr);
  1478.            break;
  1479.            case LFS_FILE_LAYOUT_MOD:
  1480.           CheckFileLayoutSummary(diskFd, segPtr, 
  1481.                 segSummaryPtr->timestamp, 
  1482.                 startAddr - blockOffset, blockOffset, 
  1483.                  segSummaryHdrPtr);
  1484.             break;
  1485.            default: {
  1486.             fprintf(stderr,"%s:CheckSummary: Unknown module type %d at %d, Size %d Blocks %d\n",
  1487.                 deviceName, segSummaryHdrPtr->moduleType,
  1488.                 startAddr - blockOffset, 
  1489.                 segSummaryHdrPtr->lengthInBytes
  1490.                , segSummaryHdrPtr->numDataBlocks);
  1491.             break;
  1492.             }
  1493.            }
  1494.            summaryPtr += segSummaryHdrPtr->lengthInBytes;
  1495.            blockOffset += segSummaryHdrPtr->numDataBlocks;
  1496.        }
  1497.        SegReleaseBlock(segPtr, (char *) segSummaryPtr);
  1498.        blockOffset = segSummaryPtr->nextSummaryBlock;
  1499.     } while( blockOffset != -1);
  1500.     SegRelease(segPtr);
  1501.     }
  1502. }
  1503.  
  1504. /*
  1505.  *----------------------------------------------------------------------
  1506.  *
  1507.  * CheckSegUsageSummary --
  1508.  *
  1509.  *    Check the segment summary regions for the seg usage map.
  1510.  *
  1511.  * Results:
  1512.  *    None.
  1513.  *
  1514.  * Side effects:
  1515.  *    None.
  1516.  *
  1517.  *----------------------------------------------------------------------
  1518.  */
  1519. static void
  1520. CheckSegUsageSummary(diskFd, segPtr, timestamp,startAddress, offset, segSummaryHdrPtr) 
  1521.     int diskFd;
  1522.     Seg *segPtr;
  1523.     int timestamp;
  1524.     int startAddress;
  1525.     int offset;
  1526.     LfsSegSummaryHdr *segSummaryHdrPtr;
  1527. {
  1528.     int blocks, *blockArray, i, startAddr, fsBlocks, j;
  1529.  
  1530.     fsBlocks = superBlockPtr->usageArray.stableMem.blockSize/blockSize;
  1531.     blocks = (segSummaryHdrPtr->lengthInBytes - sizeof(LfsSegSummaryHdr)) /
  1532.                 sizeof(int);
  1533.     if (blocks * fsBlocks != segSummaryHdrPtr->numDataBlocks) {
  1534.     majorErrors++;
  1535.     fprintf(stderr,"%s:CheckSegUsageSummary: Wrong block count; is %d should be %s\n", deviceName, blocks * fsBlocks, segSummaryHdrPtr->numDataBlocks);
  1536.     }
  1537.  
  1538.     blockArray = (int *) (segSummaryHdrPtr + 1);
  1539.     for (i = 0; i < blocks; i++) {
  1540.     startAddr = startAddress - i * fsBlocks - fsBlocks;
  1541.     if ((blockArray[i] < 0) || 
  1542.         (blockArray[i] > superBlockPtr->usageArray.stableMem.maxNumBlocks)){
  1543.         majorErrors++;
  1544.        fprintf(stderr,"%s:CheckSegUsageSummary: Bad block number %d at %d\n",
  1545.             deviceName,blockArray[i], startAddr);
  1546.         continue;
  1547.     }
  1548.     for (j = 0; j < fsBlocks; j++) { 
  1549.         blockInfoArray[startAddr + j].type = USAGE_ARRAY;
  1550.         blockInfoArray[startAddr + j].blockNum = blockArray[i];
  1551.         blockInfoArray[startAddr + j].found = TRUE;
  1552.     }
  1553.     }
  1554. }
  1555.  
  1556. /*
  1557.  *----------------------------------------------------------------------
  1558.  *
  1559.  * CheckDescMapSummary --
  1560.  *
  1561.  *    Check the segment summary regions for the seg usage map.
  1562.  *
  1563.  * Results:
  1564.  *    None.
  1565.  *
  1566.  * Side effects:
  1567.  *    None.
  1568.  *
  1569.  *----------------------------------------------------------------------
  1570.  */
  1571. static void
  1572. CheckDescMapSummary(diskFd, segPtr, timestamp,startAddress, offset, segSummaryHdrPtr) 
  1573.     int diskFd;
  1574.     Seg *segPtr;
  1575.     int timestamp;
  1576.     int startAddress;
  1577.     int offset;
  1578.     LfsSegSummaryHdr *segSummaryHdrPtr;
  1579. {
  1580.     int blocks, *blockArray, i, startAddr, fsBlocks, j;
  1581.  
  1582.     fsBlocks = superBlockPtr->descMap.stableMem.blockSize/blockSize;
  1583.     blocks = (segSummaryHdrPtr->lengthInBytes - sizeof(LfsSegSummaryHdr)) /
  1584.                 sizeof(int);
  1585.     if (blocks * fsBlocks != segSummaryHdrPtr->numDataBlocks) {
  1586.     majorErrors++;
  1587.     fprintf(stderr,"%s:CheckDescMapSummary: Wrong block count; is %d should be %s\n", deviceName,blocks * fsBlocks, segSummaryHdrPtr->numDataBlocks);
  1588.     }
  1589.     blockArray = (int *) (segSummaryHdrPtr + 1);
  1590.     for (i = 0; i < blocks; i++) {
  1591.     startAddr = startAddress - i * fsBlocks - fsBlocks;
  1592.     if ((blockArray[i] < 0) || 
  1593.         (blockArray[i] > superBlockPtr->descMap.stableMem.maxNumBlocks)){
  1594.         majorErrors++;
  1595.        fprintf(stderr,"%s:CheckDescMapSummary: Bad block number %d at %d\n",
  1596.             deviceName,blockArray[i], startAddr);
  1597.         continue;
  1598.     }
  1599.     for (j = 0; j < fsBlocks; j++) { 
  1600.         blockInfoArray[startAddr + j].type = DESC_MAP;
  1601.         blockInfoArray[startAddr + j].blockNum = blockArray[i];
  1602.         blockInfoArray[startAddr + j].found = TRUE;
  1603.     }
  1604.     }
  1605.  
  1606.  
  1607. }
  1608.  
  1609. /*
  1610.  *----------------------------------------------------------------------
  1611.  *
  1612.  * CheckFileLayoutSummary --
  1613.  *
  1614.  *    Check the segment summary regions for the file layout code.
  1615.  *
  1616.  * Results:
  1617.  *    None.
  1618.  *
  1619.  * Side effects:
  1620.  *    None.
  1621.  *
  1622.  *----------------------------------------------------------------------
  1623.  */
  1624. static void
  1625. CheckFileLayoutSummary(diskFd, segPtr, timestamp, startAddr, offset, segSummaryHdrPtr) 
  1626.     int diskFd;
  1627.     Seg  *segPtr;
  1628.     int timestamp;
  1629.     int startAddr;
  1630.     int offset;
  1631.     LfsSegSummaryHdr *segSummaryHdrPtr;
  1632. {
  1633.     char *summaryPtr, *limitPtr;
  1634.     int descMapBlocks;
  1635.     int startAddress, j, ssize;
  1636.  
  1637.     ssize = superBlockPtr->usageArray.segmentSize;
  1638.  
  1639.  
  1640.     startAddress = startAddr;
  1641.     descMapBlocks = superBlockPtr->descMap.stableMem.blockSize/blockSize;
  1642.     summaryPtr = (char *) (segSummaryHdrPtr + 1);
  1643.     limitPtr = summaryPtr + segSummaryHdrPtr->lengthInBytes - 
  1644.             sizeof(LfsSegSummaryHdr);
  1645.     while (summaryPtr < limitPtr) {
  1646.     switch (*(unsigned short *) summaryPtr) {
  1647.     case LFS_FILE_LAYOUT_DESC: {
  1648.         int        fileNumber;
  1649.         int        slot;
  1650.         LfsFileDescriptor    *descPtr;
  1651.         descPtr = (LfsFileDescriptor *) SegFetchBlock(segPtr, offset, 
  1652.                         descMapBlocks*blockSize);
  1653.         offset += descMapBlocks;
  1654.         startAddress -= descMapBlocks;
  1655.         for (slot = 0; slot < superBlockPtr->fileLayout.descPerBlock; 
  1656.         slot++) {
  1657.         int addr;
  1658.         /*
  1659.          * The descriptor block is terminated by an unallocated
  1660.          * descriptor.
  1661.          */
  1662.         if (!(descPtr[slot].common.flags & FSDM_FD_ALLOC)) {
  1663.             break;
  1664.         }
  1665.         addr = startAddress + (slot * sizeof(LfsFileDescriptor))/
  1666.                         blockSize;
  1667.         fileNumber = descPtr[slot].fileNumber;
  1668.         if ((fileNumber < 0) || 
  1669.             (fileNumber >= superBlockPtr->descMap.maxDesc)) {
  1670.             majorErrors++;
  1671.            fprintf(stderr,"%s:CheckFileLayoutSummary: bad file number %d in desc block at %d\n", deviceName, fileNumber, startAddress);
  1672.            continue;
  1673.         }
  1674.         blockInfoArray[addr].type = DESC;
  1675.         if (timestamp >= descInfoArray[fileNumber].timestamp) {
  1676.             descInfoArray[fileNumber].timestamp = timestamp;
  1677.             descInfoArray[fileNumber].flags = FD_ALLOCATED;
  1678.             if (descPtr[slot].common.fileType == FS_DIRECTORY) {
  1679.             descInfoArray[fileNumber].flags |= IS_A_DIRECTORY;
  1680.             }
  1681.             descInfoArray[fileNumber].addr = startAddress;
  1682.         }
  1683.          }
  1684.         /*
  1685.          * Skip over the summary bytes describing this block. 
  1686.          */
  1687.         summaryPtr += sizeof(LfsFileLayoutDesc);
  1688.         SegReleaseBlock(segPtr, (char *) descPtr);
  1689.         break;
  1690.     }
  1691.     case LFS_FILE_LAYOUT_DATA: {
  1692.         int    *blockArray;
  1693.         int              i;
  1694.         LfsFileLayoutSummary *fileSumPtr;
  1695.         int firstBlock;
  1696.         /*
  1697.          * We ran into a data block. If it is still alive bring it into
  1698.          * the cache. 
  1699.          */
  1700.          fileSumPtr = (LfsFileLayoutSummary *) summaryPtr;
  1701.         if ((fileSumPtr->fileNumber < 0) || 
  1702.         (fileSumPtr->fileNumber >= superBlockPtr->descMap.maxDesc)) {
  1703.         majorErrors++;
  1704.            fprintf(stderr,"%s:CheckFileLayoutSummary: bad file number %d at %d\n", deviceName, fileSumPtr->fileNumber, startAddress);
  1705.            goto out;
  1706.         }
  1707.         if (fileSumPtr->truncVersion > 
  1708.             descInfoArray[fileSumPtr->fileNumber].truncVersion) {
  1709.         descInfoArray[fileSumPtr->fileNumber].truncVersion = 
  1710.                 fileSumPtr->truncVersion;
  1711.         }
  1712.         /*
  1713.          * For each block ... 
  1714.          */
  1715.         blockArray = (int *)(summaryPtr + sizeof(LfsFileLayoutSummary));
  1716.         firstBlock = fileSumPtr->numBlocks -
  1717.          (fileSumPtr->numDataBlocks-1) * FS_BLOCK_SIZE/blockSize;
  1718.         for (i = 0; i < fileSumPtr->numDataBlocks; i++) {
  1719.         int addr, blocks;
  1720.  
  1721.         addr = startAddress - i*FS_BLOCK_SIZE/blockSize - firstBlock;
  1722.         blocks = (i == 0) ? firstBlock : (FS_BLOCK_SIZE/blockSize);
  1723.         for (j = 0; j < blocks ; j++) { 
  1724.             blockInfoArray[addr+j].type = FILE;
  1725.             blockInfoArray[addr+j].fileNum = fileSumPtr->fileNumber;
  1726.             blockInfoArray[addr+j].blockNum = blockArray[i];
  1727.             blockInfoArray[addr+j].found = TRUE;
  1728.             blockInfoArray[startAddr + j].tversion = 
  1729.                 fileSumPtr->truncVersion;
  1730.         }
  1731.         }
  1732.         out:
  1733.         startAddress = startAddress - fileSumPtr->numBlocks;
  1734.         offset += fileSumPtr->numBlocks;
  1735.         summaryPtr += sizeof(LfsFileLayoutSummary) + 
  1736.                 fileSumPtr->numDataBlocks * sizeof(int); 
  1737.         break;
  1738.       }
  1739.  
  1740.     case LFS_FILE_LAYOUT_DIR_LOG: {
  1741.         LfsFileLayoutLog    *logSumPtr;
  1742.         int            numBlocks;
  1743.         int            i,j, addr, blocks;
  1744.         LfsDirOpLogBlockHdr *hdrPtr = (LfsDirOpLogBlockHdr *) NIL;
  1745.  
  1746.         /* 
  1747.          * Directory log info is not needed during clean so we 
  1748.          * just skip over it.
  1749.          */
  1750.          logSumPtr = (LfsFileLayoutLog *) summaryPtr;
  1751.          summaryPtr = summaryPtr + sizeof(LfsFileLayoutLog);
  1752.          numBlocks = logSumPtr->numBlocks;
  1753.          addr = startAddress;
  1754.          for (i = 0; i < logSumPtr->numDataBlocks; i++) {
  1755.         if (numBlocks > FS_BLOCK_SIZE/blockSize) {
  1756.             blocks = FS_BLOCK_SIZE/blockSize;
  1757.         } else {
  1758.             blocks = numBlocks;
  1759.         }
  1760.  
  1761.             hdrPtr = (LfsDirOpLogBlockHdr *)
  1762.              SegFetchBlock(segPtr, offset, blocks*blockSize);
  1763.         addr -= blocks;
  1764.         offset += blocks;
  1765.         if (hdrPtr->magic != LFS_DIROP_LOG_MAGIC) {
  1766.             fprintf(stderr,"Bad dir op log magic number.\n");
  1767.         }
  1768.         if (showDirLog) { 
  1769.             ShowDirLogBlock(hdrPtr, addr);
  1770.         }
  1771.         for (j = 0; j < blocks; j++) {
  1772.             blockInfoArray[addr+j].type = DIRLOG;
  1773.             blockInfoArray[addr+j].found = TRUE;
  1774.         }
  1775.         numBlocks -= blocks;
  1776.          }
  1777.          startAddress = startAddress - logSumPtr->numBlocks;
  1778.          if ( hdrPtr != (LfsDirOpLogBlockHdr *) NIL) { 
  1779.          SegReleaseBlock(segPtr, (char *) hdrPtr);
  1780.         }
  1781.          break;
  1782.     }
  1783.     case LFS_FILE_LAYOUT_DBL_INDIRECT: 
  1784.     case LFS_FILE_LAYOUT_INDIRECT: 
  1785.     default: {
  1786.         panic("Unknown type");
  1787.     }
  1788.       }
  1789.     }
  1790.  
  1791. }
  1792. static char *
  1793. GetOwner(blockNum)
  1794.     int blockNum;
  1795. {
  1796.     static char buffer[128];
  1797.  
  1798.     sprintf(buffer, "<%d,%d,%d>", blockInfoArray[blockNum].type,
  1799.                 blockInfoArray[blockNum].fileNum,
  1800.                 blockInfoArray[blockNum].blockNum);
  1801.  
  1802.     return buffer;
  1803. }
  1804.  
  1805. /*
  1806.  *----------------------------------------------------------------------
  1807.  *
  1808.  * PrintSuperBlock --
  1809.  *
  1810.  *    Print super block contents.
  1811.  *
  1812.  * Results:
  1813.  *    None.
  1814.  *
  1815.  * Side effects:
  1816.  *    None.
  1817.  *
  1818.  *----------------------------------------------------------------------
  1819.  */
  1820. static void
  1821. PrintSuperBlock(superBlockPtr)
  1822.     LfsSuperBlock *superBlockPtr;
  1823. {
  1824.     printf("SuperBlock.hdr.version: %d\n", superBlockPtr->hdr.version);
  1825.     printf("SuperBlock.hdr.blockSize: %d\n", 
  1826.                 superBlockPtr->hdr.blockSize);
  1827.     printf("SuperBlock.hdr.maxCheckPointBlocks: %d\n", 
  1828.                 superBlockPtr->hdr.maxCheckPointBlocks);
  1829.     printf("SuperBlock.hdr.checkPointOffset[0]: %d\n", 
  1830.             superBlockPtr->hdr.checkPointOffset[0]);
  1831.     printf("SuperBlock.hdr.checkPointOffset[1]: %d\n", 
  1832.             superBlockPtr->hdr.checkPointOffset[1]);
  1833.     printf("SuperBlock.hdr.logStartOffset: %d\n", 
  1834.             superBlockPtr->hdr.logStartOffset);
  1835.     printf("SuperBlock.hdr.maxNumCacheBlocks: %d\n", 
  1836.             superBlockPtr->hdr.maxNumCacheBlocks);
  1837.     printf("SuperBlock.descMap.version: %d\n", superBlockPtr->descMap.version);
  1838.     printf("SuperBlock.descMap.maxDesc: %d\n", superBlockPtr->descMap.maxDesc);
  1839.     printf("SuperBlock.descMap.stableMem.blockSize: %d\n", 
  1840.             superBlockPtr->descMap.stableMem.blockSize);
  1841.     printf("SuperBlock.descMap.stableMem.maxNumBlocks: %d\n", 
  1842.             superBlockPtr->descMap.stableMem.maxNumBlocks);
  1843.     printf("SuperBlock.usageArray.segmentSize: %d\n", 
  1844.                 superBlockPtr->usageArray.segmentSize);
  1845.     printf("SuperBlock.usageArray.numberSegments: %d\n", 
  1846.                 superBlockPtr->usageArray.numberSegments);
  1847.     printf("SuperBlock.usageArray.minNumClean: %d\n", 
  1848.                 superBlockPtr->usageArray.minNumClean);
  1849.     printf("SuperBlock.usageArray.minFreeBlocks: %d\n", 
  1850.                 superBlockPtr->usageArray.minFreeBlocks);
  1851.     printf("SuperBlock.usageArray.stableMem.blockSize: %d\n", 
  1852.             superBlockPtr->descMap.stableMem.blockSize);
  1853.     printf("SuperBlock.usageArray.stableMem.maxNumBlocks: %d\n", 
  1854.             superBlockPtr->descMap.stableMem.maxNumBlocks);
  1855.     printf("SuperBlock.fileLayout.descPerBlock: %d\n", 
  1856.                 superBlockPtr->fileLayout.descPerBlock);
  1857. }
  1858.  
  1859.  
  1860. /*
  1861.  *----------------------------------------------------------------------
  1862.  *
  1863.  * PrintCheckPointHdr --
  1864.  *
  1865.  *    Print check point header contents.
  1866.  *
  1867.  * Results:
  1868.  *    None.
  1869.  *
  1870.  * Side effects:
  1871.  *    None.
  1872.  *
  1873.  *----------------------------------------------------------------------
  1874.  */
  1875. static void
  1876. PrintCheckPointHdr(headerPtr, region)
  1877.     LfsCheckPointHdr *headerPtr;
  1878.     int region;
  1879. {
  1880.     printf("CheckPointHdr[%d].timestamp: %d\n", region, headerPtr->timestamp);
  1881.     printf("CheckPointHdr[%d].size: %d\n", region, headerPtr->size);
  1882.     printf("CheckPointHdr[%d].version: %d\n", region, headerPtr->version);
  1883.     printf("CheckPointHdr[%d].domainPrefix: %s\n", region, 
  1884.                     headerPtr->domainPrefix);
  1885.     printf("CheckPointHdr[%d].domainNumber: %d\n", region,
  1886.                 headerPtr->domainNumber);
  1887.     printf("CheckPointHdr[%d].attachSeconds: %d\n", region, 
  1888.             headerPtr->attachSeconds);
  1889.     printf("CheckPointHdr[%d].detachSeconds: %d\n", region, 
  1890.             headerPtr->detachSeconds);
  1891.     printf("CheckPointHdr[%d].serverID: %d\n", region, 
  1892.             headerPtr->serverID);
  1893. }
  1894.  
  1895. static void
  1896. ShowDirLogBlock(hdrPtr, addr)
  1897.     LfsDirOpLogBlockHdr *hdrPtr;
  1898.     int addr;
  1899. {
  1900.     LfsDirOpLogEntry *entryPtr, *limitPtr;
  1901.  
  1902.     printf("Dirlog block at %d, size %d\n", addr, hdrPtr->size);
  1903.     limitPtr = (LfsDirOpLogEntry *) (((char *) hdrPtr) + hdrPtr->size);
  1904.     entryPtr = (LfsDirOpLogEntry *) (hdrPtr+1);
  1905.     while (entryPtr < limitPtr) {
  1906.     printf("LogSeqNum %d opFlags 0x%x dirFile %d dirOffset %d linkCount %d\n",
  1907.         entryPtr->hdr.logSeqNum, entryPtr->hdr.opFlags, 
  1908.         entryPtr->hdr.dirFileNumber,
  1909.         entryPtr->hdr.dirOffset, entryPtr->hdr.linkCount);
  1910.     entryPtr->dirEntry.fileName[entryPtr->dirEntry.nameLength] = '\0';
  1911.     printf("    File %d Name %s\n", entryPtr->dirEntry.fileNumber, 
  1912.         entryPtr->dirEntry.fileName);
  1913.     entryPtr = (LfsDirOpLogEntry *) 
  1914.              (((char *)entryPtr) + LFS_DIR_OP_LOG_ENTRY_SIZE(entryPtr));
  1915.     }
  1916.  
  1917. }
  1918.  
  1919. static char *
  1920. FmtTime()
  1921. {
  1922.      struct timeval tim;
  1923.      time_t  timeVal;
  1924.      static char timeBuffer[128];
  1925.  
  1926.      if (gettimeofday(&tim, (struct timezone *) NULL)) {
  1927.      perror("gettimeofday");
  1928.      return "Unknown";
  1929.      }
  1930.      timeVal = tim.tv_sec;
  1931.      (void)strcpy(timeBuffer, ctime(&timeVal) + sizeof("Sun Sep 16 ")-1);
  1932.  
  1933.      sprintf(timeBuffer+sizeof("01:03:52")-1,".%03d", tim.tv_usec/1000);
  1934.      return timeBuffer;
  1935. }
  1936.  
  1937. static Seg *
  1938. SegInit(diskFd, segNumber)
  1939.     int    diskFd;
  1940.     int    segNumber;    /* Segment number to operate on. */
  1941. {
  1942.     static Seg seg;
  1943.     seg.segNo = segNumber;
  1944.     seg.segSizeInBlocks = superBlockPtr->usageArray.segmentSize/blockSize;
  1945.     seg.diskFd = diskFd;
  1946.     return &seg;
  1947. }
  1948.  
  1949. static int
  1950. SegStartAddr(segPtr)
  1951.     Seg    *segPtr;
  1952. {
  1953.     return  segPtr->segNo * segPtr->segSizeInBlocks + 
  1954.             superBlockPtr->hdr.logStartOffset;
  1955. }
  1956. static char *
  1957. SegFetchBlock(segPtr, blockOffset, size)
  1958.     Seg        *segPtr;
  1959.     int        blockOffset;
  1960.     int        size;
  1961. {
  1962.     char *buf;
  1963.     int      startAddr;
  1964.  
  1965.     startAddr = SegStartAddr(segPtr) + segPtr->segSizeInBlocks - blockOffset -
  1966.         size/blockSize;
  1967.     buf = malloc(size);
  1968.  
  1969.     if (DiskRead(segPtr->diskFd, startAddr , size, buf) != size) {
  1970.     fprintf(stderr,"%s:SegFetchBlock: Can't read seg %d offset %d.\n", deviceName, segPtr->segNo, blockOffset);
  1971.     }
  1972.     return buf;
  1973. }
  1974. static void
  1975. SegReleaseBlock(segPtr, memPtr)
  1976.     Seg        *segPtr;
  1977.     char    *memPtr;
  1978. {
  1979.     free(memPtr);
  1980. }
  1981. static void
  1982. SegRelease(segPtr)
  1983.     Seg        *segPtr;
  1984. {
  1985. }
  1986.  
  1987. static Boolean 
  1988. IsZero(dataPtr, size)
  1989.     register char *dataPtr;
  1990.     register int    size;
  1991. {
  1992.     for (; size > 0; dataPtr++, size--) {
  1993.     if (*dataPtr) {
  1994.         return FALSE;
  1995.     }
  1996.     }
  1997.     return TRUE;
  1998.  
  1999. }
  2000.  
  2001.